package jpave.manager;

/*****************************************************
 * Seems to be a mix of the Load Library Add and the Run Annotation Add. 
 * but then some of Load Library is also in Edit TransLibPanel
 * and some of Run Anno is in EditAnnoPanel
 */
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;

import util.Debug.ErrorReport;
import util.ui.UserPrompt;

public class EditPanel extends JPanel {
	private static final long serialVersionUID = 2806917997839245167L;

	private static final int MODE_EXP_LIB = 1;
	private static final int MODE_ANNODB = 2;
	private static final int MODE_TRANS_LIB = 3;
	
	public static final int COLUMN_LABEL_WIDTH = 140;
	public static final int TEXTFIELD_WIDTH_SHORT = 15;
	public static final int TEXTFIELD_WIDTH = 30;
	public static final int NUM_FIELD_WIDTH = 5;
	
	public static final int FILE_VALIDATION_LINES = 3;
	
	public static final String [] REP_LIB_LABELS = { "Library ID", "Rep ID" };
	public static final String [] REP_LIB_SYMBOLS = { "libid", "rep" };
	public static final Class<?> [] REP_LIB_TYPES = { String.class, String.class };
	
	public static final String [] TRANS_LIB_LABELS = { "Library ID", "Sequence File", "Quality File", "Count File", "Read Count prefix", "5' suffix", "3' suffix"};
	public static final String [] TRANS_LIB_SYMBOLS = { "translibid", "seqfile", "qualfile", "expfile", "prefix", "fiveprimesuf", "threeprimesuf"};
	public static final Class<?> [] TRANS_LIB_TYPES = { String.class, File.class, File.class, File.class, String.class, String.class, String.class };
	
	public static final String [] EXP_LIB_LABELS = { "libid" };
	public static final String [] EXP_LIB_SYMBOLS = { "libid" };
	public static final Class<?> [] EXP_LIB_TYPES = { String.class };

	// THESE are not used; defined explicitly in EditAnnoPanel 
	public static final String [] ANNODB_LABELS = { "Taxonomy", "Blast File", "Fasta File",  "Blast Parameters", "Subset", "Date" };
	public static final String [] ANNODB_SYMBOLS = { "JPAVE_DBTaxo_", "JPAVE_unitrans_DBblast_", "JPAVE_DBfasta_", "JPAVE_DBargs_", "JPAVE_unitrans_subset", "JPAVE_DBdate_" };
	public static final Class<?> [] ANNODB_TYPES = { String.class, File.class, File.class, String.class, Boolean.class, String.class };
	
	// if these are changed, also change in ManagerFrame updateExpLibEditUI, updateExpLibUI, updateTransLibEditUI, updateTransLibUI
	public static final String [] ATTRIBUTE_LABELS = { "Title", "Species", "Cultivar", "Strain", "Tissue", "Stage", "Treatment",  "Year", "Source" };
	public static final String [] ATTRIBUTE_SYMBOLS = { "title", "organism", "cultivar", "strain", "tissue", "stage", "treatment", "year", "source" };
	public static final Class<?> [] ATTRIBUTE_TYPES = { String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class, String.class };
	
	public static EditPanel createExpLibEditPanel(ManagerFrame parent) { return new EditPanel(parent, MODE_EXP_LIB, EXP_LIB_LABELS, EXP_LIB_SYMBOLS, EXP_LIB_TYPES); }
	public static EditPanel createAnnoDBEditPanel(ManagerFrame parent) { return new EditPanel(parent, MODE_ANNODB, ANNODB_LABELS, ANNODB_SYMBOLS, ANNODB_TYPES); }
	
	public EditPanel(ManagerFrame parent, int mode, String [] labels, String [] symbol, Class<?> [] types) {
		nMode = mode;
		theParentFrame = parent;
		
		theSymbols = new String[symbol.length];
		for(int x=0; x<theSymbols.length; x++)
			theSymbols[x] = symbol[x];
		makeFields(labels, types);
		
		setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
		setAlignmentX(Component.LEFT_ALIGNMENT);
		setBackground(ManagerFrame.BGCOLOR);
		
		JPanel innerPanel = new JPanel();
		innerPanel.setLayout(new BoxLayout(innerPanel, BoxLayout.PAGE_AXIS));
		innerPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
		innerPanel.setBackground(ManagerFrame.BGCOLOR);
		
		JPanel row = new JPanel();
		row.setLayout(new BoxLayout(row, BoxLayout.LINE_AXIS));
		row.setBackground(ManagerFrame.BGCOLOR);
		row.setAlignmentX(Component.LEFT_ALIGNMENT);
		
		JLabel title = null;
		if(nMode == MODE_ANNODB)
			title = new JLabel("AnnoDB Add/Edit");
		else
			title = new JLabel("Count Library Attributes");
		title.setFont(innerPanel.getFont().deriveFont(Font.BOLD, 18));
		
		row.add(Box.createHorizontalGlue());
		row.add(title);
		row.add(Box.createHorizontalGlue());
		innerPanel.add(row);
		innerPanel.add(Box.createVerticalStrut(20));

		for(int x=0; x<theLabels.length; x++) {
			row = new JPanel();
			row.setLayout(new BoxLayout(row, BoxLayout.LINE_AXIS));
			row.setBackground(ManagerFrame.BGCOLOR);
			row.setAlignmentX(Component.LEFT_ALIGNMENT);
			
			int buffer = COLUMN_LABEL_WIDTH - theLabels[x].getPreferredSize().width;
			row.add(theLabels[x]);
			if(buffer > 0)
				row.add(Box.createHorizontalStrut(buffer));
			row.add(theComps[x]);
			
			innerPanel.add(row);
			innerPanel.add(Box.createVerticalStrut(5));
			
			if(theLabels[x].getText().equals("Trans/Lib ID")) { // FIXME no such string
				row = new JPanel();
				row.setLayout(new BoxLayout(row, BoxLayout.LINE_AXIS));
				row.setBackground(ManagerFrame.BGCOLOR);
				row.setAlignmentX(Component.LEFT_ALIGNMENT);
				
				row.add(Box.createHorizontalStrut(COLUMN_LABEL_WIDTH));
				row.add(new JLabel("(Less than 8 characters, no spaces)"));

				innerPanel.add(row);
				innerPanel.add(Box.createVerticalStrut(5));
			}
		}
		
		//Attribute panel
		innerPanel.add(Box.createVerticalStrut(10));
		
		if(nMode != MODE_ANNODB) {
			for(int x=0; x < theAttributeLabels.length; x++) {
				row = new JPanel();
				row.setLayout(new BoxLayout(row, BoxLayout.LINE_AXIS));
				row.setBackground(ManagerFrame.BGCOLOR);
				row.setAlignmentX(Component.LEFT_ALIGNMENT);
				
				int buffer = COLUMN_LABEL_WIDTH - theAttributeLabels[x].getPreferredSize().width;
				row.add(theAttributeLabels[x]);
				if(buffer > 0)
					row.add(Box.createHorizontalStrut(buffer));
				row.add(theAttributeComps[x]);
				
				innerPanel.add(row);
				innerPanel.add(Box.createVerticalStrut(5));
			}
		}
		
		btnKeep = new JButton("Keep");
		btnKeep.setBackground(ManagerFrame.BGCOLOR);
		btnKeep.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				theParentFrame.updateExpLibUI();
				theParentFrame.updateExpLibProperties();
				setVisible(false);
				theParentFrame.setMainPanelVisible(true);
				
				theParentFrame.updateUI();
				theParentFrame.saveProject();
				
				theParentFrame.setFrameMode(ManagerFrame.FRAME_MODE_MAIN);
			}
		});
		btnDiscard = new JButton("Discard");
		btnDiscard.setBackground(ManagerFrame.BGCOLOR);
		btnDiscard.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(theParentFrame.isRemoveExpLibOnDiscard()) {
					theParentFrame.clearCurrentExpLib();
					theParentFrame.updateUI();
				}
				setVisible(false);
				theParentFrame.setMainPanelVisible(true);
				
				theParentFrame.setFrameMode(ManagerFrame.FRAME_MODE_MAIN);
			}
		});
		btnHelp = new JButton("Help");
		btnHelp.setBackground(ManagerFrame.HELPCOLOR);
		btnHelp.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(nMode == MODE_ANNODB)
					UserPrompt.displayHTMLResourceHelp(theParentFrame, "AnnoDB Help", "html/runSingleTCW/EditAnnoDBPanel.html");
				else
					UserPrompt.displayHTMLResourceHelp(theParentFrame, "Expression Library Help", "html/runSingleTCW/EditExpLibPanel.html");
			}
		});

		
		JPanel buttonRow = new JPanel();
		buttonRow.setLayout(new BoxLayout(buttonRow, BoxLayout.LINE_AXIS));
		buttonRow.setAlignmentX(Component.CENTER_ALIGNMENT);
		buttonRow.setBackground(ManagerFrame.BGCOLOR);
		
		if(mode == MODE_ANNODB) {
			btnResetToDefaults = new JButton("Set To Defaults");
			btnResetToDefaults.setBackground(ManagerFrame.BGCOLOR);
			buttonRow.add(btnResetToDefaults);
			buttonRow.add(Box.createHorizontalStrut(15));
		}
		
		buttonRow.add(btnKeep);
		buttonRow.add(Box.createHorizontalStrut(15));
		buttonRow.add(btnDiscard);
		buttonRow.add(Box.createHorizontalStrut(15));
		buttonRow.add(btnHelp);
		
		buttonRow.setMaximumSize(buttonRow.getPreferredSize());
		buttonRow.setMinimumSize(buttonRow.getPreferredSize());
		
		innerPanel.setMaximumSize(innerPanel.getPreferredSize());
		innerPanel.setMinimumSize(innerPanel.getPreferredSize());
		
		add(innerPanel);
		add(Box.createVerticalStrut(10));
		add(buttonRow);
	}
	
	public void resetUI() {
		resetComps(theComps);
		if(nMode != MODE_ANNODB)
			resetComps(theAttributeComps);
	}
	
	public void setEnabled(String symbol, boolean enabled) {
		for(int x=0; x<theSymbols.length; x++) {
			if(theSymbols[x].equals(symbol)) {
				theComps[x].setEnabled(enabled);
			}
		}
	}
	
	public Object getValue(String symbol) {
		Object retVal = null;
		for(int x=0; x<theSymbols.length && retVal == null; x++) {
			if(theSymbols[x].equals(symbol)) {
				if(theComps[x] instanceof JTextField)
					retVal = new String(((JTextField)theComps[x]).getText());
				else if(theComps[x] instanceof FileTextField)
					retVal = new String(((FileTextField)theComps[x]).getText());
				else if(theComps[x] instanceof JCheckBox)
					retVal = new Boolean(((JCheckBox)theComps[x]).isSelected());
			}
		}
		
		if(nMode != MODE_ANNODB) {
			for(int x=0; x<ATTRIBUTE_SYMBOLS.length && retVal == null; x++) {
				if(ATTRIBUTE_SYMBOLS[x].equals(symbol)) {
					if(theAttributeComps[x] instanceof JTextField)
						retVal = new String(((JTextField)theAttributeComps[x]).getText());
					else if(theAttributeComps[x] instanceof FileTextField)
						retVal = new String(((FileTextField)theAttributeComps[x]).getText());
					else if(theAttributeComps[x] instanceof JCheckBox)
						retVal = new Boolean(((JCheckBox)theAttributeComps[x]).isSelected());
				}
			}
		}
		
		return retVal;
	}
	
	public void setValue(String symbol, Object value) {
		boolean valueSet = false;
		for(int x=0; x<theSymbols.length && !valueSet; x++) {
			if(theSymbols[x].equals(symbol)) {
				valueSet = true;
				
				if(theComps[x] instanceof JTextField)
					((JTextField)theComps[x]).setText((String)value);
				else if(theComps[x] instanceof FileTextField)
					((FileTextField)theComps[x]).setText((String)value);
				else if(theComps[x] instanceof JCheckBox)
					((JCheckBox)theComps[x]).setSelected((Boolean)value);
			}
		}

		if(nMode != MODE_ANNODB) {
			for(int x=0; x<ATTRIBUTE_SYMBOLS.length && !valueSet; x++) {
				if(ATTRIBUTE_SYMBOLS[x].equals(symbol)) {
					valueSet = true;
					
					if(theAttributeComps[x] instanceof JTextField)
						((JTextField)theAttributeComps[x]).setText((String)value);
					else if(theAttributeComps[x] instanceof FileTextField)
						((FileTextField)theAttributeComps[x]).setText((String)value);
					else if(theAttributeComps[x] instanceof JCheckBox)
						((JCheckBox)theAttributeComps[x]).setSelected((Boolean)value);
				}
			}
		}
	}
	
	private static void resetComps(Component [] comps) {
		for(int x=0; x<comps.length; x++) {
			if(comps[x] instanceof JTextField)
				((JTextField)comps[x]).setText("");
			else if(comps[x] instanceof FileTextField)
				((FileTextField)comps[x]).setText("");
			else if(comps[x] instanceof JCheckBox)
				((JCheckBox)comps[x]).setSelected(false);
		}
	}
	
	private void makeFields(String [] labels,  Class<?> [] types) {
		theLabels = new JLabel[labels.length];
		for(int x=0; x<theLabels.length; x++) {
			theLabels[x] = new JLabel(labels[x]);
		}
		
		if(nMode != MODE_ANNODB) {
			theAttributeLabels = new JLabel[ATTRIBUTE_LABELS.length];
			for(int x=0; x<ATTRIBUTE_LABELS.length; x++) {
				theAttributeLabels[x] = new JLabel(ATTRIBUTE_LABELS[x]);
			}
		}

		theComps = new JComponent[types.length];
		for(int x=0; x<theComps.length; x++) {
			theComps[x] = getComponent(labels[x], types[x]);
		}
		
		if(nMode != MODE_ANNODB) {
			theAttributeComps = new JComponent[ATTRIBUTE_TYPES.length];
			for(int x=0; x<ATTRIBUTE_TYPES.length; x++) {
				theAttributeComps[x] = getComponent(ATTRIBUTE_LABELS[x], ATTRIBUTE_TYPES[x]);
			}
		}
	}
	
	private JComponent getComponent(String key, Class<?> type) {
		JComponent retVal = null;
		if(type == String.class) {
			retVal = new JTextField(TEXTFIELD_WIDTH);
			retVal.setMaximumSize(retVal.getPreferredSize());
			((JTextField)retVal).addCaretListener(updateListener);
		}
		else if(type == File.class) {
			retVal = new FileTextField(theParentFrame, key, TEXTFIELD_WIDTH);
			((FileTextField)retVal).addCaretListener(updateListener);
			((FileTextField)retVal).addActionListener(fileSelectListener);
		}
		else if(type == Integer.class) {
			retVal = new JTextField(NUM_FIELD_WIDTH);
			retVal.setMaximumSize(retVal.getPreferredSize());
			((JTextField)retVal).addCaretListener(updateListener);
		}
		else if(type == Boolean.class) {
			retVal = new JCheckBox();
		}
		retVal.setBackground(ManagerFrame.BGCOLOR);
		
		return retVal;
	}
	
	private ActionListener fileSelectListener = new ActionListener() {
		public void actionPerformed(ActionEvent arg0) {
		}
	};
	
	//TODO
	private CaretListener updateListener = new CaretListener() {
		public void caretUpdate(CaretEvent e) {
			if(nMode == MODE_ANNODB) {
				int blastIdx = -1;
				int fastaIdx = -1;
				int paramIdx = -1;
				for(int x=0; x<theLabels.length && (blastIdx < 0 || fastaIdx < 0 || paramIdx < 0); x++) {
					if(theLabels[x].getText().equals("Blast File"))
						blastIdx = x;
					else if(theLabels[x].getText().equals("Fasta File"))
						fastaIdx = x;
					else if(theLabels[x].getText().equals("Blast Parameters"))
						paramIdx = x;
				}
				
				if(blastIdx >= 0 && fastaIdx >= 0 && paramIdx >= 0) {
					if(((FileTextField)theComps[fastaIdx]).getText().length() > 0) {
						theLabels[blastIdx].setEnabled(false);
						((FileTextField)theComps[blastIdx]).setEnabled(false);
					}
					else {
						theLabels[blastIdx].setEnabled(true);
						((FileTextField)theComps[blastIdx]).setEnabled(true);
					}
					
					if(((FileTextField)theComps[blastIdx]).getText().length() > 0) {
						theLabels[fastaIdx].setEnabled(false);
						((FileTextField)theComps[fastaIdx]).setEnabled(false);
						theLabels[paramIdx].setEnabled(false);
						theComps[paramIdx].setEnabled(false);
					}
					else {
						theLabels[fastaIdx].setEnabled(true);
						((FileTextField)theComps[fastaIdx]).setEnabled(true);
						theLabels[paramIdx].setEnabled(true);
						theComps[paramIdx].setEnabled(true);
					}
				}
			}
			else if(nMode == MODE_TRANS_LIB) {
				int expFileIdx = -1;
				int fivePrimeIdx = -1;
				int threePrimeIdx = -1;

				for(int x=0; x<theLabels.length && (expFileIdx < 0 || fivePrimeIdx < 0 || threePrimeIdx < 0); x++) {
					if(theLabels[x].getText().equals("Read Count File"))
						expFileIdx = x;
					else if(theLabels[x].getText().equals("Five prime suffix"))
						fivePrimeIdx = x;
					else if(theLabels[x].getText().equals("Three prime suffix"))
						threePrimeIdx = x;
				}
				
				if(expFileIdx >= 0 && fivePrimeIdx >= 0 && threePrimeIdx >= 0) {
					if(((FileTextField)theComps[expFileIdx]).getText().length() > 0) {
						theLabels[fivePrimeIdx].setEnabled(false);
						theComps[fivePrimeIdx].setEnabled(false);
						theLabels[threePrimeIdx].setEnabled(false);
						theComps[threePrimeIdx].setEnabled(false);
					} 
					else {
						theLabels[fivePrimeIdx].setEnabled(true);
						theComps[fivePrimeIdx].setEnabled(true);
						theLabels[threePrimeIdx].setEnabled(true);
						theComps[threePrimeIdx].setEnabled(true);
					}
				}
			}
			
			if(nMode == MODE_TRANS_LIB) {
				int idIdx = -1;
				int seqIdx = -1;
				int qualIdx = -1;

				for(int x=0; x<theLabels.length && (idIdx < 0 || seqIdx < 0 || qualIdx < 0); x++) {
					if(theLabels[x].getText().equals("Library ID")) // FIXME was Trans/Lib ID though no string
						idIdx = x;
					else if(theLabels[x].getText().equals("Sequence File"))
						seqIdx = x;
					else if(theLabels[x].getText().equals("Quality File"))
						qualIdx = x;
				}
				
				if(idIdx >= 0 && seqIdx >= 0 && qualIdx >= 0) {
					if(((JTextField)theComps[idIdx]).getText().length() > 0 && ((FileTextField)theComps[seqIdx]).getText().length() > 0) {
						if(((JTextField)theComps[idIdx]).getText().matches("[a-zA-Z0-9_]*")) { 
							boolean seqValid = isValidSeqFile(theParentFrame, ((FileTextField)theComps[seqIdx]).getText()); 
							boolean qualValid = isValidQualFile(theParentFrame, ((FileTextField)theComps[seqIdx]).getText(), ((FileTextField)theComps[qualIdx]).getText());
							
							boolean enableKeep = true;
							
							if(!seqValid) {
								enableKeep = false;
							}
							if(((FileTextField)theComps[qualIdx]).getText().length() > 0 && !qualValid) {
								enableKeep = false;
							}
							btnKeep.setEnabled(enableKeep);
						}
						else
							btnKeep.setEnabled(false);
					}
					else
						btnKeep.setEnabled(false);
				}
			}
			else if(nMode == MODE_ANNODB) {
				
			}
		}
	};
	
	private void updateTitle(String title) {
		int titleIdx = -1;

		for(int x=0; x<theAttributeLabels.length && titleIdx < 0; x++) {
			if(theAttributeLabels[x].getText().equals("Title"))
				titleIdx = x;
		}
		
		if(titleIdx >= 0) {
			String path = ((JTextField)theAttributeComps[titleIdx]).getText();
			if(path.length() == 0) {
				int pos = 0;
				while((pos = title.indexOf('/')) >= 0) {
					title = title.substring(pos+1, title.length());
				}
				if((pos = title.indexOf('.')) >=0)
					title = title.substring(0, pos);
				((JTextField)theAttributeComps[titleIdx]).setText(title);
			}
		}		
	}
	
	public static boolean isValidSeqFile(ManagerFrame parentFrame, String seqFile) {
		try {
			if(!seqFile.startsWith("/"))
				seqFile = parentFrame.getLibPath() + "/" + seqFile;
			BufferedReader reader = new BufferedReader(new FileReader(seqFile));
			String line = null;
			int counter = 0;
			while((line = reader.readLine()) != null && counter < FILE_VALIDATION_LINES) {
				if(!line.startsWith(">")) {
					System.err.println("Error in sequence file: ID not properly formatted '" + line + "'");
					return false;
				}
				line = reader.readLine();
				if(line == null) {
					System.err.println("Error: sequence missing");
					return false;
				}
				if(!line.matches("[AaCcGgTtUuRrYySsWwKkMmBbDdHhVvNn\\.\\-]*")) {
					System.err.println("Error: improperly formatted sequence:\n\n" + line);
					return false;
				}
				counter++;
			}
			return true;
		}
		catch(Exception e) {
			return false;
		}
	}
	
	public static boolean isValidQualFile(ManagerFrame parentFrame, String seqFile, String qualFile) {
		try {
			if(!seqFile.startsWith("/"))
				seqFile = parentFrame.getLibPath() + "/" + seqFile;
			if(!qualFile.startsWith("/"))
				qualFile = parentFrame.getLibPath() + "/" + qualFile;

			BufferedReader seqRead = new BufferedReader(new FileReader(seqFile));
			BufferedReader qualRead = new BufferedReader(new FileReader(qualFile));
			
			String seqLine = null, qualLine = null;
			int counter = 0;
			while(((seqLine = seqRead.readLine()) != null) && ((qualLine = qualRead.readLine()) != null) && counter < FILE_VALIDATION_LINES) {
				if(!seqLine.equals(qualLine)) {
					return false;
				}
				seqLine = seqRead.readLine();
				qualLine = qualRead.readLine();
				
				if(seqLine == null || qualLine == null)
					return false;
				counter++;
			}
			return true;
		}
		catch(Exception e) {
			return false;
		}
	}
	
	private JPanel getInstance() { return this; }
	
	private JLabel [] theLabels = null;
	private JComponent [] theComps = null;
	private String [] theSymbols = null;
	
	private JLabel [] theAttributeLabels = null;
	private JComponent [] theAttributeComps = null;
	
	private JButton btnResetToDefaults = null;
	private JButton btnKeep = null;
	private JButton btnDiscard = null;
	private JButton btnHelp = null;
	
	private int nMode = -1;
	private ManagerFrame theParentFrame = null;

	public class FileTextField extends JPanel {
		private static final long serialVersionUID = 6670096855895700182L;
		
		public FileTextField(ManagerFrame parentFrame, final String label, int size) {
			theParentFrame = parentFrame;
			setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
			setAlignmentX(Component.LEFT_ALIGNMENT);
			setBackground(ManagerFrame.BGCOLOR);
			
			txtValue = new JTextField(size);
			Dimension dTxt = txtValue.getPreferredSize(); 
			txtValue.setMaximumSize(dTxt);
			txtValue.setMinimumSize(dTxt);
			
			btnFindFile = new JButton("...");
			btnFindFile.setBackground(ManagerFrame.BGCOLOR);
			Dimension dBtn = new Dimension();
			dBtn.width = btnFindFile.getPreferredSize().width;
			dBtn.height = dTxt.height;
			
			btnFindFile.setMaximumSize(dBtn);
			btnFindFile.setMinimumSize(dBtn);
			btnFindFile.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent arg0) {
					try {
						JFileChooser fc = new JFileChooser();
						if(nMode == MODE_TRANS_LIB)
							fc.setCurrentDirectory(theParentFrame.getLibPath());
						else
							fc.setCurrentDirectory(theParentFrame.getProjPath());
						
						if(fc.showOpenDialog(getInstance()) == JFileChooser.APPROVE_OPTION) {
							if(nMode == MODE_ANNODB) {
								String path = fc.getSelectedFile().getPath();
								int index = path.indexOf(theParentFrame.getAnnoDBPath().getAbsolutePath()); 
								if(index >= 0) {
									txtValue.setText(path.substring(index + theParentFrame.getAnnoDBPath().getAbsolutePath().length() + 1));
								}
								else
									txtValue.setText(fc.getSelectedFile().getPath());
							}
							else if(nMode == MODE_TRANS_LIB) {
								String path = fc.getSelectedFile().getAbsolutePath();
								int index = path.indexOf(theParentFrame.getLibPath().getAbsolutePath());
								if(label.equals("Sequence File"))
									updateTitle(path);
								if(index >= 0) {
									txtValue.setText(path.substring(index + theParentFrame.getLibPath().getAbsolutePath().length() + 1));
								}
								else
									txtValue.setText(fc.getSelectedFile().getAbsolutePath());
							}
						}
					}
					catch(Exception e) {
						ErrorReport.prtReport(e, "Error finding file");
					}
					
				}});
			
			add(txtValue);
			add(btnFindFile);
		}
		
		public void addCaretListener(CaretListener l) { txtValue.addCaretListener(l); }
		public void addActionListener(ActionListener l) { btnFindFile.addActionListener(l); }
		
		public void setText(String text) { txtValue.setText(text); }
		public String getText() { return txtValue.getText(); }
		
		public void setEnabled(boolean enabled) {
			txtValue.setEnabled(enabled);
			btnFindFile.setEnabled(enabled);
		}
		
		private ManagerFrame theParentFrame = null;
		
		private JTextField txtValue = null;
		private JButton btnFindFile = null;
	}
}
